package com.zxq.modbus.container;

import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import com.zxq.modbus.config.LockConfig;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


/**
 * 为了异步读取数据
 */
@Slf4j
public class LockContainer {

    /**
     * 容器控制
     */
    static ConcurrentMap<ChannelHandlerContext, Condition> channelLockContainer = new ConcurrentHashMap<>();

    /**
     * 数据容器
     */
    static ConcurrentMap<ChannelHandlerContext, byte[]> channelDataContainer = new ConcurrentHashMap<>();


    /**
     * 独占锁
     */
    static ReentrantLock reentrantLock = new ReentrantLock();
    /**
     * 核心算法，这里是想让他异步把数据回传回来
     * 锁通道
     * @param channel 通道
     */
    public final static byte[] lockChannel(ChannelHandlerContext channel, byte[] data) {
            reentrantLock.lock();
            Condition condition = reentrantLock.newCondition();
            channelLockContainer.put(channel, condition);
            log.info(" channel:" + channel.toString() + "post:" + HexBin.encode(data));
                 //channelLockContainer.get(channel);
            channel.writeAndFlush(Unpooled.copiedBuffer(data));
            try {
                condition.await(LockConfig.getTimeOut(), TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            byte[] msg = channelDataContainer.get(channel);
            log.info(" channel:" + channel.toString() + " rec:" + HexBin.encode(msg));

            channelLockContainer.remove(channel);
            channelDataContainer.remove(channel);

            reentrantLock.unlock();
            return msg;
    }

    /**
     * 解锁通道
     * @param channel 通道
     */
    public final static void unLockChannel(ChannelHandlerContext channel, byte[] data) {
            reentrantLock.lock();
            Condition condition = channelLockContainer.get(channel);
            if (condition == null) {
                log.info("condition null");
                // log.info("channel:" + channel.toString() + "rec empty!" );
                return;
            }
           // System.out.println("unlock Data:" + HexBin.encode(data));
            channelDataContainer.put(channel, data);
            condition.signal();
            reentrantLock.unlock();
    }

    /**
     * 锁住注册Id。解锁后获取结构
     * @param registerId 注册Id
     * @return
     */
    /**
    public final static PlatformModBusResult lockRegisterId(String registerId) {
        PlatformModBusResult platformModBusResult = null;
        synchronized (registerId) {
            reentrantLock.lock();
            Condition condition = reentrantLock.newCondition();
            platformLockContainer.put(registerId, condition);
            try {
                condition.await(LockConfig.getTimeOut(), TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            platformModBusResult = platformResultContainer.get(registerId);
            platformLockContainer.remove(platformModBusResult);
            reentrantLock.unlock();
        }
        return platformModBusResult;

    }
    */

    /**
     * 解锁注册id，通知获取对应结果
     * @param registerId 注册id
     * @param platformModBusResult 平台结果
     */
    /**
    public final static void unLockRegisterId(String registerId,  PlatformModBusResult platformModBusResult) {
        //log.info("channel:" + channel.toString() + "rec:" +HexBin.encode(data));
        synchronized (registerId) {
            reentrantLock.lock();
            Condition condition = platformLockContainer.get(registerId);
            platformResultContainer.put(registerId, platformModBusResult);
            condition.signal();
            reentrantLock.unlock();
        }
    }*/


}
